#pragma once

/* flatmap, 每个是一个字节 */
#include <metalc/meta/_meta.h>
#include <dinfra/flatmap.h>


/* 外部meta */


/* 1级flatmap */
/*  name - 名字
	metatype - meta数据类型(必须是基础类型)
	ptr_bits - 内存数据的指针个数(用于确定flatmap总大小)
	oalloc - os_alloc
	ofree - os_free
*/
#define DEF_FLAT_EXT_MMETA(name, metatype, total_bits, low_bits, oalloc, ofree)\
DECL_MMETA(name, metatype) \
DEF_FLATMAP(metatype, name, BIT(total_bits - low_bits), oalloc, ofree)\
SAI void mmeta_init_##name() { flatmap_create_##name(); }\
SAI void mmeta_tinit_##name(){};\
SAI size_t  mmeta_ocupysize_##name (size_t msize) { PARAM_USED(msize); return 0; }\
SAI mmeta_t *mmeta_by_ptr_##name (void *ptr, size_t size, size_t msize, fvoid **pfptr){\
	PARAM_USED(size, msize);\
	*pfptr = (fvoid *)ptr;\
	return &flatmap_##name [(size_t)ptr >> low_bits];}\
SAI mmeta_t *mmeta_by_fptr_##name (fvoid *fptr, size_t size, void **pptr){\
	PARAM_USED(size);\
	*pptr = (void *)fptr;\
	return &flatmap_##name [(size_t)fptr >> low_bits];}


/* 2级基数树 1 radix + 1 flatmap, rdx映射flatmap指针, 能够优化一定的虚拟内存占用 */
#include <dinfra/radix.h>

/* 可以把1级基数树大小提出来 */
#define DEF_L2_EXT_MMETA(name, metatype, total_bits, low_bits, oalloc, ofree)\
static radix_t rdx_##name[512] ALIGN(PAGE_SIZE);					   \
DEF_RADIX_FIND_COMP(name##_1, 9, id_val_decoder, id_val_encoder, oalloc)\
DEF_RADIX_FIND(name, name##_1)\
DECL_MMETA(name, metatype) \
SAI void mmeta_init_##name() {  /*  name##_radix_find( rdx_##name,  &rdx_##name, 0); */ };\
SAI void mmeta_tinit_##name(){};\
SAI size_t  mmeta_ocupysize_##name (size_t msize) { PARAM_USED(msize); return 0; }\
SAI mmeta_t *mmeta_by_ptr_##name (void *ptr, size_t size, size_t msize, fvoid **pfptr){\
	PARAM_USED(size, msize);\
	*pfptr = (fvoid *)ptr;\
	radix_t *prdx;\
	metatype *fm = (metatype *)( name##_radix_find(rdx_##name, &prdx, (size_t)ptr >> (total_bits - 9))); /* 取高9位 */ \
	if (!fm) { fm = oalloc(sizeof(metatype) * BIT(total_bits - low_bits - 9)); *prdx = (radix_t)fm; } /* flatmap未建立 */ \
	return &fm[((size_t)ptr & MASK_LOW(total_bits - 9)) >> low_bits]; /* mask剩下的 */}\
SAI mmeta_t *mmeta_by_fptr_##name (fvoid *fptr, size_t size, void **pptr){\
	PARAM_USED(size);\
	*pptr = (void *)fptr;\
	radix_t *prdx;\
	metatype *fm = (metatype *)( name##_radix_find(rdx_##name, &prdx, (size_t)fptr >> (total_bits - 9))); /* 取高9位 */ \
	return  &fm[((size_t)fptr & MASK_LOW(total_bits - 9)) >> low_bits]; }
